import os
import csv
import pandas as pd
from loguru import logger


# 添加登录失败原因描述
def fail_reason_4625(temp_path):
    file_name_4625 = f'{temp_path}/4625.csv'
    if os.path.getsize(file_name_4625) and os.path.exists(file_name_4625):
        new_lines = []
        fail_reason_dict = {"0xc0000072": "账户目前禁用", "0xc0000064": "用户名不存在",
                            "0xc000006a": "用户名正确，但密码错误",
                            "0xc0000234": "用户当前锁定", "0xc000006f": "用户试图登录天的外周或时间限制",
                            "0xc0000070": "工作站的限制",
                            "0xc0000193": "账户过期", "0xc0000071": "过期的密码",
                            "0xc0000133": "时钟之间的直流和其他电脑不太同步",
                            "0xc0000224": "在下一次登录用户需要修改密码",
                            "0xc0000225": "显然一个缺陷在Windows而不是一个风险",
                            "0xc000015b": "没有被授予该用户请求类型", "0xc000006d": "似乎是由于系统问题和不安全"}
        with open(file_name_4625, 'r', encoding="gbk") as fd:
            lines = csv.reader(fd)
            for line in lines:
                if 'EventID' not in line[0]:
                    if line[5] in fail_reason_dict:
                        line[5] = fail_reason_dict[line[5]]
                    new_lines.append(line)
        df = pd.DataFrame(new_lines)
        df.columns = ['EventID', 'TimeGenerated', 'User', 'EventType', 'EventTypeName', 'FailureReason', 'IP', 'Port']
        df.to_csv(file_name_4625, index=False, mode="w", encoding="gbk")


# 添加远程登录相关描述
def rdp_connection_describe(file_name):
    if os.path.exists(file_name) and os.path.getsize(file_name):
        new_lines = []
        # 1149和261是Microsoft-Windows-TerminalServices-RemoteConnectionManager%4Operational.evtx
        # 21\22\23\24是Microsoft-Windows-TerminalServices-LocalSessionManager%4Operational.evtx
        # (没有登录成功也会出现1149，需要注意)
        rdp_connection_describe_dict = {"1149": "远程桌面服务: 用户身份验证已成功",
                                        "261": "侦听程序 RDP-Tcp 已收到一个连接",
                                        "21": "远程桌面服务: 会话登录成功", "22": "已收到Shell启动通知",
                                        "23": "会话注销成功", "24": "会话已断开连接",
                                        "25": "会话重新连接成功"}
        with open(file_name, 'r', encoding="gbk") as fd:
            lines = csv.reader(fd)
            for line in lines:
                if 'EventID' not in line[1]:
                    if line[1] in rdp_connection_describe_dict:
                        line.insert(6, rdp_connection_describe_dict[line[1]])
                    new_lines.append(line)
        df = pd.DataFrame(new_lines)
        df.columns = ['TimeGenerated', 'EventID', 'EventType', 'User', 'Domain/会话ID', 'ComputerName(本机)',
                      'Describe', 'IP']
        df.to_csv(file_name, index=False, mode="w", encoding="gbk")


# 添加用户操作相关描述
def user_action_describe(file_name):
    if os.path.exists(file_name) and os.path.getsize(file_name):
        new_lines = []
        user_action_dict = {"4728": "已向启用了安全性的全局组中添加某个成员", "4720": "已创建用户帐户",
                            "4722": "已启用用户帐户", "4738": "已更改用户帐户",
                            "4732": "已向启用了安全性的本地组中添加某个成员",
                            "4733": "已从启用了安全性的本地组中删除某个成员",
                            "4729": "已从启用了安全性的全局组中删除某个成员",
                            "4726": "已删除用户帐户"}
        with open(file_name, 'r', encoding="gbk") as fd:
            lines = csv.reader(fd)
            for line in lines:
                if 'EventID' not in line[0]:
                    if line[0] in user_action_dict:
                        line.insert(6, user_action_dict[line[0]])
                    else:
                        line.insert(6, "未自定义")
                    new_lines.append(line)
        df = pd.DataFrame(new_lines)
        df.columns = ['EventID', 'TimeGenerated', 'SourceUser', 'TargetUser', 'EventType', 'EventTypeName', 'Describe']
        df.to_csv(file_name, index=False, mode="w", encoding="gbk")


def schtasks_describe(file_name):
    if os.path.exists(file_name) and os.path.getsize(file_name):
        schtasks_dict = {"4698": "已创建计划任务", "4699": "已删除计划任务", "4700": "已启用计划任务",
                         "4701": "计划任务被禁用", "4702": "计划任务已更新"}
        new_lines = []
        with open(file_name, "r", encoding="gbk") as fd:
            lines = csv.reader(fd)
            for line in lines:
                if 'EventID' not in line[0]:
                    if line[0] in schtasks_dict:
                        line.insert(6, schtasks_dict[line[0]])
                    else:
                        line.insert(6, "未自定义")
                    new_lines.append(line)
            df = pd.DataFrame(new_lines)
            df.columns = ['EventID', 'TimeGenerated', 'User', 'Schtasks', 'EventType', 'EventTypeName', 'Describe']
            df.to_csv(file_name, index=False, mode="w", encoding="gbk")


# 将同类型操作整合为一个文件
def result_to_one_step(temp_path, csv_file_name_list, target_csv_file_name):
    try:
        for csv_file_name in csv_file_name_list:
            csv_file_path = f'{temp_path}/{csv_file_name}'
            if os.path.getsize(csv_file_path) and "user_" in csv_file_name:
                with open(csv_file_path, 'r', encoding="gbk") as fd:
                    lines = csv.reader(fd)
                    if os.path.exists(target_csv_file_name):
                        lines = list(lines)[1:]
                    df = pd.DataFrame(lines)
                    df.to_csv(target_csv_file_name, index=False, header=False, mode="a", encoding="gbk")
                os.remove(csv_file_path)
    except Exception as e:
        logger.error(f"result_to_on_step error:{e}")


def add_description(temp_path):
    fail_reason_4625(temp_path)
    remote_file_name = f'{temp_path}/remote.csv'
    local_file_name = f'{temp_path}/rdp.csv'
    if os.path.exists(remote_file_name):
        rdp_connection_describe(remote_file_name)
    if os.path.exists(local_file_name):
        rdp_connection_describe(local_file_name)
    user_action_file_name = f"{temp_path}/user_action.csv"
    result_to_one_step(temp_path, os.listdir(temp_path), user_action_file_name)
    if os.path.exists(user_action_file_name):
        user_action_describe(user_action_file_name)
    if os.path.exists(f'{temp_path}/schtasks.csv'):
        schtasks_describe(f'{temp_path}/schtasks.csv')
